package com.hibase.upms.service.role.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hibase.common.constant.ResponseCode;
import com.hibase.common.exception.HibaseAssert;
import com.hibase.common.exception.HibaseException;
import com.hibase.common.util.EntityUtil;
import com.hibase.common.util.UserContext;
import com.hibase.core.mybatis.service.BaseServiceImpl;
import com.hibase.core.web.entity.OperationIdEntity;
import com.hibase.upms.entity.menu.MdsMenu;
import com.hibase.upms.entity.role.MdsRole;
import com.hibase.upms.entity.role.vo.*;
import com.hibase.upms.entity.rolemenu.MdsRoleMenu;
import com.hibase.upms.entity.userrole.MdsUserRole;
import com.hibase.upms.mapper.role.MdsRoleMapper;
import com.hibase.upms.service.role.MdsRoleService;
import com.hibase.upms.service.rolemenu.MdsRoleMenuService;
import com.hibase.upms.service.userrole.MdsUserRoleService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ChrisCui
 * @since 2019-04-16
 */
@Slf4j
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
@RequiredArgsConstructor
public class MdsRoleServiceImpl extends BaseServiceImpl<MdsRoleMapper, MdsRole> implements MdsRoleService {

    private final MdsUserRoleService userRoleService;

    private final MdsRoleMenuService roleMenuService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeRole(MdsRoleUpdateVO updateVO) {
        MdsRole mdsRole = EntityUtil.transform(updateVO, MdsRole.class);
        if (StrUtil.isBlank(mdsRole.getId())) {
            mdsRole.setBeActive(true);
            mdsRole.setSysCode(RandomUtil.randomString(10) + DateUtil.date().getTime());
        }
        super.store(mdsRole);
        //保存角色下用户信息
        insAndDelRoleUser(mdsRole.getId(), updateVO.getUserId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class, readOnly = false)
    public void changeRoleStatus(List<String> ids, boolean recordStatus) {
        List<MdsRole> roleList = super.listByIds(ids);
        roleList.forEach(role -> {
            HibaseAssert.isFalse(role.getBeActive() == recordStatus,
                    "{} 重复操作",role.getCode());
            role.setBeActive(recordStatus);
        });
        if(CollUtil.isNotEmpty(roleList)){
            super.storeBatch(roleList);
        }
    }

    @Override
    public PageInfo<MdsRole> selectList(MdsRoleSearchVO searchVO) {

        QueryWrapper<MdsRole> queryWrapper = new QueryWrapper<>();

        if (StrUtil.isNotBlank(searchVO.getCode())) {

            queryWrapper.like("code", searchVO.getCode());
        }
        if (StrUtil.isNotBlank(searchVO.getName())) {

            queryWrapper.like("name", searchVO.getName());
        }
        if (StrUtil.isNotBlank(searchVO.getKeyWord())) {
            queryWrapper.like("code", searchVO.getKeyWord()).or().like("name", searchVO.getKeyWord());
        }
        if (ObjectUtil.isNotEmpty(searchVO.getBeActive())) {
            queryWrapper.eq("be_active", searchVO.getBeActive());
        }
        PageInfo<MdsRole> result = super.page(searchVO, queryWrapper);

        return result;
    }

    @Override
    public PageInfo<MdsRoleUserViewVO> selectRoleUserList(OperationIdEntity idEntity) {
        Map<String, Object> conditionMap = new HashMap<>();
        if (StrUtil.isNotBlank(idEntity.getId())) {
            conditionMap.put("id", idEntity.getId());
        }
        Page<MdsRoleUserViewVO> page = PageHelper.startPage(idEntity.getCurrentPage(), idEntity.getPageSize());
        this.baseMapper.selectRoleUserList(conditionMap);
        PageInfo<MdsRoleUserViewVO> result = new PageInfo<>(page);
        return result;
    }

    @Override
    public PageInfo<MdsRoleUserViewVO> selectRoleNoUserList(OperationIdEntity idEntity) {

        Map<String, Object> conditionMap = new HashMap<>();

        if (StrUtil.isNotBlank(idEntity.getId())) {
            conditionMap.put("id", idEntity.getId());
        }

        Page<MdsRoleUserViewVO> page = PageHelper.startPage(idEntity.getCurrentPage(), idEntity.getPageSize());

        this.baseMapper.selectRoleNoUserList(conditionMap);
        PageInfo<MdsRoleUserViewVO> result = new PageInfo<>(page);

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insAndDelRoleUser(String roleId, List<String> userIds) {
        // 先删除此角色对应的用户旧数据
        if (StrUtil.isNotBlank(roleId)) {
            userRoleService.deleteBy(Wrappers.<MdsUserRole>lambdaQuery()
                    .eq(MdsUserRole::getRoleId,roleId));
        }
        if (CollUtil.isNotEmpty(userIds)) {
            List<MdsUserRole> userRoleList = new ArrayList<>();
            for (String userId : userIds) {
                MdsUserRole mdsUserRole = new MdsUserRole();
                mdsUserRole.setUserId(userId);
                mdsUserRole.setRoleId(roleId);
                userRoleList.add(mdsUserRole);
            }
            userRoleService.storeBatch(userRoleList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, readOnly = false)
    public void deleteRoleUser(MdsRoleUserOpVO mdsRoleUserOpVo) {

        if (CollUtil.isNotEmpty(mdsRoleUserOpVo.getUserId())) {
            for (String userId : mdsRoleUserOpVo.getUserId()) {
                MdsUserRole userRole = userRoleService.getOne(new QueryWrapper<MdsUserRole>().eq("role_id", mdsRoleUserOpVo.getRoleId()).eq("user_id", userId));
                if (ObjectUtils.isNull(userRole)) {
                    throw new HibaseException(ResponseCode.DATA_NOT_EXISTS.getCode(), ResponseCode.DATA_NOT_EXISTS.getMessage());
                }
                userRoleService.deleteBy(userRole);
            }
        }
    }

    @Override
    public List<MdsMenu> selectRoleMenuList(OperationIdEntity idEntity) {
        List<MdsRoleMenu> roleMenuList = roleMenuService.getListByRoleId(idEntity.getId());
        List<MdsMenu> mdsMenus = new ArrayList<MdsMenu>();
        boolean typeFlag;
        for (MdsRoleMenu p : roleMenuList) {
            //step 1 处理
            typeFlag = false;
            if (p.getType().equals("PAGE")) {
                for (MdsRoleMenu mdsRoleMenu : roleMenuList) {
                    if (mdsRoleMenu.getParentId().equals(p.getId())) {
                        typeFlag = true;
                    }
                }
            }
            if (typeFlag) {
                continue;
            }
            // step 2
            MdsMenu menu = new MdsMenu();
            menu.setId(p.getMenuId());
            menu.setCode(p.getMenuId());
            menu.setName(p.getMenuId());
            mdsMenus.add(menu);
        }
        return mdsMenus;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insAndDelRoleMenu(MdsRoleMenuOpVO mdsRoleMenuOpVo) {
        // 先删除此角色对应的菜单权限旧数据
        if (StrUtil.isNotBlank(mdsRoleMenuOpVo.getRoleId())) {
            roleMenuService.deleteBy(new QueryWrapper<MdsRoleMenu>().eq("role_id", mdsRoleMenuOpVo.getRoleId()));
        }
        if (CollUtil.isNotEmpty(mdsRoleMenuOpVo.getMenuId())) {
            List<MdsRoleMenu> mdsRoleMenus = new ArrayList<>();
            //TODO 2021年9月28日09:51:57 由于前端没办法传父级ID ， 后台处理 把前端提交的所有menu_id 父级ID查出来，查出来以后去重，再查父级ID的父级ID...
            Set<String> parentIdSet = new HashSet<>();
            parentIdSet.addAll(mdsRoleMenuOpVo.getMenuId());
            recursionParentId(new HashSet<>(parentIdSet), parentIdSet);
            if (CollUtil.isNotEmpty(parentIdSet)) {
                parentIdSet.stream().forEach(m -> {
                    MdsRoleMenu mdsRoleMenu = new MdsRoleMenu();
                    mdsRoleMenu.setRoleId(mdsRoleMenuOpVo.getRoleId());
                    mdsRoleMenu.setMenuId(m);

                    mdsRoleMenus.add(mdsRoleMenu);
                });
            }
            roleMenuService.storeBatch(mdsRoleMenus);
        }
    }

    /**
     * @param idSet
     * @param parentId 返回结果
     * @return
     * @Title: MdsRoleServiceImpl
     * @Description: TODO
     * @author TimBrian
     * @since 2021年9月28日 上午11:48:40
     */
    public Set<String> recursionParentId(Set<String> idSet, Set<String> parentId) {
        idSet = roleMenuService.seleParentIdById(new ArrayList<>(idSet));
        if (idSet != null && idSet.size() > 0) {
            parentId.addAll(idSet);
            recursionParentId(idSet, parentId);
        }
        return parentId;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insAndDelRoleMenuByPageConfig(MdsRoleMenuOpVO mdsRoleMenuOpVo) {
        // 先删除此角色对应的菜单权限旧数据
        if (StrUtil.isNotBlank(mdsRoleMenuOpVo.getRoleId())) {

            roleMenuService.deleteBy(new QueryWrapper<MdsRoleMenu>().eq("role_id", mdsRoleMenuOpVo.getRoleId()));
        }

        if (CollUtil.isNotEmpty(mdsRoleMenuOpVo.getMenuId())) {

            List<MdsRoleMenu> mdsRoleMenus = new ArrayList<>();

            mdsRoleMenuOpVo.getMenuId().forEach(m -> {

                MdsRoleMenu mdsRoleMenu = new MdsRoleMenu();
                mdsRoleMenu.setRoleId(mdsRoleMenuOpVo.getRoleId());
                mdsRoleMenu.setMenuId(m);

                mdsRoleMenus.add(mdsRoleMenu);
            });

            roleMenuService.storeBatch(mdsRoleMenus);
        }

    }

    @Override
    public void refreshPermissions() {

//        RedissonUtils.refreshSecurity();
    }

    @Override
    public PageInfo selectCurrentUserRoleList(OperationIdEntity idEntity) {
        //得到当前
        String userId = UserContext.get().getId();
        List<MdsUserRole> list = userRoleService.list(Wrappers.<MdsUserRole>lambdaQuery()
                .in(MdsUserRole::getUserId, userId, idEntity.getId())
                .select(MdsUserRole::getRoleId)
        );
        return super.page(idEntity, Wrappers.<MdsRole>query()
                .in("id", list.stream().map(MdsUserRole::getRoleId).collect(Collectors.toList()))
        );
    }
}
